#include "mvc/model/station.h"
#include "common/geometry_calcs.h"

/**
  * Make a station with the 'iref' and 'fref' references curves with
  * 'n_knots - 2' knots between iref[pos] and fref[pos], 0 <= pos <= iref size.
  * iref - the initial reference curve
  * fref - the final reference curves
  * n_knots - the total knots between a point in the initial reference curve and the
  * final reference curve, both included.
  */
Station::Station(const Refcurve &iref, const Refcurve &fref, int n_knots)
{
    int total_size;

    rc_size = iref.size();
    total_size = rc_size * n_knots;
    frc_ipos = total_size - rc_size;
    knots.resize(iref.size() * n_knots);

    for(int i = 0; i < iref.size(); i++)
    {
        knots[i] = iref[i];
        knots[i + frc_ipos] = fref[i];
    }

    is_calculated = false;
}

/**
  * Creates an station with a vector of points.
  * _knots - the knots to create the station.
  * row_knots - the row size
  */
Station::Station(QVector<Point3D *> _knots, int row_knots)
{
    rc_size = row_knots;

    for(int i = 0; i < _knots.size(); i++)
    {
        Point3D *cp = _knots.at(i);
        knots.push_back(new Point3D(cp->x, cp->y, cp->z));
    }

    is_calculated = false;
}

/*
 * Station destructor
 * Station isn't responsible for reference curves memory
 */
Station::~Station()
{
    for(int i = rc_size; i < knots.size() - rc_size; i++)
        delete knots[i];
}

/**
  * Calculate all station's points using the rect equation.
  */
void Station::calculate_points()
{
    Point3D *fst, *last, *u;
    double increment;

    if(not is_calculated)
    {
        increment = 1.0 / ((total_points(true) / rc_size) - 1);
        int current = rc_size;
        double lambda = increment;
        while(current < frc_ipos)
        {
            for(int row = 0; row < rc_size; row++)
            {
                fst = knots[row];
                last = knots[row + frc_ipos];
                u = (*fst) - (*last);
                knots[current] = find_a_point(*fst, *u, lambda);
                current++;
            }

            lambda += increment;
        }

        is_calculated = true;
    }
}

/**
  * returns the rows size of the station
  */
int Station::rows() const
{
    return rc_size;
}

/**
  * returns the points of the station
  */
const QVector<Point3D *> &Station::get_points(bool repeat) const
{
    return knots;
}

/**
  * returns the total points of the station.
  */
int Station::total_points(bool repeat) const
{
    return knots.size();
}
